﻿/************************************************************************
 * AIDE - Automata Identification Engine
 * Copyright (C) 2012-2013 Ali Khalili (khalili_DOT_ir_@SIGN_gmail_DOT_com)
 * **********************************************************************
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License (LGPL) published 
 * by the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version. This program is distributed without any
 * warranty. See the GNU Lesser General Public License for more details. 
 * ***********************************************************************
 * File         :     
 * Description  :     
 * Change log   :     	-Date:  Change
 ************************************************************************/

using System;
using System.Collections.Generic;

using SMLib.Base;//for List<T>
//using EnGine.Formalism;//for IState

namespace SMLib.DataTypes
{
    /// <summary>
    /// A Queue (First in-First out list)
    /// </summary>
    /// <typeparam name="T">Type of elements</typeparam>
    public class EnQueue<T> : IStateVariable
    //    where T : ICloneable
    {
        List<T> theQueue;
        int maxSize;
        public EnQueue(int maxSize = int.MaxValue)
        {
            if (!(typeof(T).IsPrimitive || (typeof(T) == typeof(string)) || (typeof(T).IsEnum)
                || (typeof(T).GetInterface(typeof(IStateVariable).FullName) != null)))
                throw new Exception("The type of T in EnQueue<T> should be builtin, string or IStateVariable!");

            this.maxSize = maxSize;
            theQueue = new List<T>();
        }

        public void Add(T value)
        {
            if (theQueue.Count == maxSize)
                return;
            theQueue.Add(value);
        }

        public int Count
        {
            get
            {
                return theQueue.Count;
            }
        }

        public void Clear()
        {
            theQueue.Clear();
        }

        public T RemoveLast()
        {
            if (theQueue.Count == 0)
                throw new Exception("Empty Queue!");

            T t = theQueue[Count - 1];
            theQueue.RemoveAt(Count - 1);
            return t;
        }

        public override string ToString()
        {
            return theQueue.Count.ToString();
        }

        public override bool Equals(object obj)
        {
            if (this.GetType() != obj.GetType())
                return false;
            EnQueue<T> secondobj = obj as EnQueue<T>;
            if (this.theQueue.Count != secondobj.theQueue.Count)
                return false;
            for (int i = 0; i < theQueue.Count; i++)
            {
                if (!theQueue[i].Equals(secondobj.theQueue[i]))
                    return false;
            }
            return true;
        }

        public override int GetHashCode()
        {
            //To Do:[implement this function]
            return base.GetHashCode();
        }

        //Check it!
        public object Clone()
        {
            EnQueue<T> obj = new EnQueue<T>();
            if ((typeof(T)).IsPrimitive || typeof(T).IsEnum || typeof(T) == typeof(string))
            {
                foreach (T o in theQueue)
                    obj.theQueue.Add(o);
            }
            else
            {
                foreach (object o in theQueue)
                    obj.theQueue.Add((T)((o as ICloneable).Clone()));
            }
            return obj;
        }


        #region IState Members

        public object[] Fields
        {
            get { throw new NotImplementedException(); }
        }

        public string GetLocationName(int locationId)
        {
            throw new NotImplementedException();
        }

        public int LocationValuesCount
        {
            get { throw new NotImplementedException(); }
        }

        public object GetLocation(int locationId)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IComparable Members

        public int CompareTo(object obj)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
